﻿using System;
using System.Collections.Generic;
using System.IO;

namespace MetaMapics.Pbf.Indexed
{
  public class NumericIndexedPbfReader<T> : IDisposable where T : IPbfStreamable, new()
  {
    private string filePath;
    private Stream stream;
    private PbfReader reader;
    private long[] keys;
    private long[] offsets;

    public NumericIndexedPbfReader(string filePath)
    {
      this.filePath = filePath;
      stream = File.OpenRead(filePath);
      reader = new PbfReader(stream);
      Readindex();
    }

    public bool Get(long key, out T value)
    {
      value = default(T);
      int index = Array.BinarySearch<long>(keys, key);
      if (index < 0)
        return false;
      long offset = offsets[index];
      stream.Seek(offset, SeekOrigin.Begin);
      long position = stream.Position;
      long length = stream.Length;
      reader.ReadTag();
      value = new T();
      reader.ReadNestedMessage(value);
      return true;
    }

    private void Readindex()
    {
      string indexFilePath = filePath.Substring(0, filePath.LastIndexOf('.')) + ".pbx";
      using (var stream = File.OpenRead(indexFilePath))
      using (var reader = new PbfReader(stream))
      {
        foreach (int fieldNum in reader.Fields())
          switch (fieldNum)
          {
            case 1:
              int count = reader.ReadInt();
              break;
            case 2:
              keys = reader.ReadPackedLong(PbfFieldType.Sfixed64);
              break;
            case 3:
              offsets = reader.ReadPackedLong(PbfFieldType.Sfixed64);
              break;
            default:
              reader.IgnoreField();
              break;
          }
      }
    }

    public void Close()
    {
      Dispose();
    }

    public void Dispose()
    {
      reader.Close();
      stream.Close();
    }
  }
}
